﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Reflection;


namespace spring.stp6.db.provider.EntityFrameworkExtensions
{

        public static class ObjectContextExtensions
        {
            public static void CascadingDeleteOnSubmit(this ObjectContext context, object entity)
            {
                List<object> objects2Delete = new List<object>();
                CascadingDeleteOnSubmit(context, entity, objects2Delete);
                foreach (object o in objects2Delete)
                {
                    context.DeleteObject(o);
                }
            }

            public static void CascadingDeleteOnSubmit(this ObjectContext context, object entity, List<object> object2Delete)
            {
                Type entityType = entity.GetType();
                PropertyInfo[] entityProperties = entityType.GetProperties();
                //查找是否有“AssociationAttribute”标记的属性
                //（Linq中有“AssociationAttribute”标记的属性代表外表）
                IEnumerable<PropertyInfo> associationProperties = entityProperties.Where(
                     c => c.GetCustomAttributes(true).Any(
                         attrbute => attrbute.GetType().Name == "EdmRelationshipNavigationPropertyAttribute")
                         & c.PropertyType.IsGenericType);//该属性必需是泛型

                //其他表有外键关联的记录
                foreach (PropertyInfo associationProperty in associationProperties)
                {
                    //获取Property值
                    object propertyValue = associationProperty.GetValue(entity, null);
                    if (propertyValue.GetType().GetGenericTypeDefinition() == typeof(EntityCollection<>))
                    {
                        //Property是EntitySet`1类型的值，如EntitySet<Element>，
                        //而EntitySet`1有IEnumerable接口
                        IEnumerable enumerable = (IEnumerable)propertyValue;
                        foreach (object o in enumerable)
                        {
                            //递归，删除关联的关联
                            CascadingDeleteOnSubmit(context, o, object2Delete);
                        }
                    }
                }

                try
                {
                    //把要删除的关系放进object2Delete，
                    //这里没有直接删除，是因为直接删除会报错，foreach里的东西，不让删除
                    //这个函数的Linq版可以直接删除。
                    object2Delete.Add(entity);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }    

}
